<template>
    <el-dialog v-model="isOpen" title="局部LISA空间自相关分析结果" :border="true" :width="1500" align-center>
        <div class="result_show">
            <div class="left">
                <!-- 基本参数信息 -->
                <el-descriptions column="2" border>
                    <el-descriptions-item label="权重类型">{{ formatWeightType(originalData.weightType) }}</el-descriptions-item>
                    <el-descriptions-item label="KNN参数" v-if="originalData.weightType === 'KNN'">{{ originalData.knnK }}</el-descriptions-item>
                    <el-descriptions-item label="距离阈值" v-if="originalData.distanceThreshold">{{ originalData.distanceThreshold }}</el-descriptions-item>
                    <el-descriptions-item label="显著性水平">{{ originalData.significanceLevel }}</el-descriptions-item>
                    <el-descriptions-item label="置换次数">{{ originalData.permutations }}</el-descriptions-item>
                    <el-descriptions-item label="计算时间">{{ result.computeTime }}ms</el-descriptions-item>
                </el-descriptions>

                <el-divider />

                <!-- 空间聚类分布地图 -->
                <div class="mapContainer" ref="mapContainer" @mouseleave="handleMouseLeave">
                    <div class="custom-tooltip" v-if="tooltipVisible" :style="{ left: tooltipX + 'px', top: tooltipY + 'px' }">
                        <p>名称: {{ tooltipData?.name }}</p>
                        <p>ID_0: {{ tooltipData?.ID_0 }}</p>
                        <p>ID_1: {{ tooltipData?.ID_1 }}</p>
                        <p>ISO: {{ tooltipData?.ISO }}</p>
                        <p>数值: {{ tooltipData?.value }}</p>
                        <p>聚类类型: {{ tooltipData.clusterType }}</p>
                        <p>局部Moran值: {{ tooltipData.localMoranValue?.toFixed(2) }}</p>
                    </div>
                </div>

                <el-divider />

                <!-- 聚类类型说明 -->
                <el-card>
                    <div class="flex">
                        <div class="flex center">
                            <span class="color-box hh"></span>
                            <span>HH：高值-高值聚集</span>
                        </div>

                        <div class="flex center">
                            <span class="color-box ll"></span>
                            <span>LL：低值-低值聚集</span>
                        </div>

                        <div class="flex center">
                            <span class="color-box lh"></span>
                            <span>LH：低值-高值聚集</span>
                        </div>

                        <div class="flex center">
                            <span class="color-box hl"></span>
                            <span>HL：高值-低值聚集</span>
                        </div>

                        <div class="flex center">
                            <span class="color-box ns"></span>
                            <span>NS：不显著</span>
                        </div>
                    </div>
                </el-card>
            </div>

            <div class="right">
                <!-- 详细数据表格 -->
                <el-table :data="tableData" border size="small">
                    <el-table-column prop="featureId" label="要素ID" width="120" />

                    <el-table-column prop="name" label="名称" width="150">
                        <template #default="scope">
                            {{ tableData.find(item => item.featureId === scope.row.featureId)?.name }}
                        </template>
                    </el-table-column>

                    <el-table-column prop="clusterType" label="聚类类型" width="80">
                        <template #default="scope">
                            <span :class="`cluster-tag ${scope.row.clusterType.toLowerCase()}`">{{ scope.row.clusterType }}</span>
                        </template>
                    </el-table-column>

                    <el-table-column prop="localMoranValue" label="局部Moran值" width="100">
                        <template #default="scope">{{ scope.row.localMoranValue.toFixed(2) }}</template>
                    </el-table-column>

                    <el-table-column prop="pvalue" label="P值">
                        <template #default="scope">{{ scope.row.pvalue.toFixed(2) }}</template>
                    </el-table-column>

                    <el-table-column prop="significant" label="显著性">
                        <template #default="scope">
                            <el-tag :type="scope.row.significant ? 'success' : 'info'">
                                {{ scope.row.significant ? "显著" : "不显著" }}
                            </el-tag>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
        </div>

        <template #footer>
            <div class="dialog-footer">
                <el-button type="primary" @click="isOpen = false">
                    关闭
                </el-button>
            </div>
        </template>
    </el-dialog>
</template>

<script setup>
import { computed, nextTick, onUnmounted, ref, watch } from "vue"
import Map                                             from "ol/Map"
import View                                            from "ol/View"
import GeoJSON                                         from "ol/format/GeoJSON"
import VectorLayer                                     from "ol/layer/Vector"
import VectorSource                                    from "ol/source/Vector"
import { Fill, Stroke, Style }                         from "ol/style"
import { fromLonLat }                                  from "ol/proj"
import XYZ                                             from "ol/source/XYZ"
import TileLayer                                       from "ol/layer/Tile"

let isOpen = defineModel()
let props  = defineProps([ "originalData", "result" ])

// 地图相关
let mapContainer = ref(null)
let map          = null
let vectorLayer  = null
let hoverFeature = ref(null) // 当前悬停的要素
let allFeatures  = ref([]) // 存储所有要素信息，用于表格展示

// 提示框相关
let tooltipVisible = ref(false)
let tooltipX       = ref(0)
let tooltipY       = ref(0)
let tooltipData    = ref({})

// 处理鼠标离开地图容器的情况
function handleMouseLeave(){
    tooltipVisible.value = false
    hoverFeature.value   = null
}

// 格式化表格数据（包含properties信息）
const tableData = computed(() => {
    if(!props.result || allFeatures.value.length === 0){
        return []
    }

    return props.result.featureIds.map((id, index) => {
        // 找到对应的要素，获取properties信息
        const feature    = allFeatures.value[index]
        const properties = feature?.getProperties() || {}

        return {
            featureId      : id,
            name           : properties.name || "", // 从properties获取名称
            clusterType    : props.result.clusterTypes[index],
            localMoranValue: props.result.localMoranValues[index],
            pvalue         : props.result.pvalues[index],
            significant    : props.result.pvalues[index] < props.result.significanceLevel,
        }
    })
})

// 聚类类型颜色映射
const clusterColors = {
    "HH": "rgba(231, 76, 60, 0.7)",    // 红色
    "LL": "rgba(52, 152, 219, 0.7)",    // 蓝色
    "LH": "rgba(243, 156, 18, 0.7)",    // 橙色
    "HL": "rgba(155, 89, 182, 0.7)",    // 紫色
    "NS": "rgba(149, 165, 166, 0.5)",     // 灰色
}

// 根据聚类类型获取样式
function getClusterStyle(clusterType){
    return new Style({
        fill  : new Fill({
            color: clusterColors[clusterType] || clusterColors.NS,
        }),
        stroke: new Stroke({
            color: "#fff",
            width: 1,
        }),
    })
}

// 初始化地图
function initMap(){
    nextTick(() => {
        if(!mapContainer.value || !props.originalData.geoJson){
            return
        }

        // 解析父组件传递的geoJson数据
        const geojsonFormat = new GeoJSON()
        const features      = geojsonFormat.readFeatures(JSON.parse(props.originalData.geoJson), {
            dataProjection   : "EPSG:4326",
            featureProjection: "EPSG:3857",
        })

        // 存储所有要素，用于表格关联
        allFeatures.value = features

        // 为每个要素添加聚类信息属性
        features.forEach((feature, index) => {
            if(props.result && props.result.clusterTypes[index]){
                // 保留原始properties
                const originalProperties = feature.getProperties()

                // 添加分析结果属性
                feature.setProperties({
                    ...originalProperties, // 保留原始属性
                    clusterType    : props.result.clusterTypes[index],
                    localMoranValue: props.result.localMoranValues[index],
                    pvalue         : props.result.pvalues[index],
                    significant    : props.result.pvalues[index] < props.result.significanceLevel,
                    featureId      : props.result.featureIds[index],
                })
                feature.setStyle(getClusterStyle(props.result.clusterTypes[index]))
            }
        })

        // 创建基础图层
        let baseLayer = new TileLayer({
            source: new XYZ({
                url: "https://webrd0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1",
            }),
        })

        // 创建矢量数据源
        const vectorSource = new VectorSource({
            features: features,
        })

        // 创建矢量图层
        vectorLayer = new VectorLayer({
            source: vectorSource,
        })

        // 创建地图实例（不含底图）
        map = new Map({
            target  : mapContainer.value,
            layers  : [ baseLayer, vectorLayer ],
            view    : new View({
                center: fromLonLat([ 114.17, 22.28 ]),
                zoom  : 8,
            }),
            controls: [],
        })

        // 鼠标移动事件 - 检测要素悬停
        map.on("pointermove", (evt) => {
            if(!map){
                return
            }

            // 获取当前鼠标位置的要素
            map.forEachFeatureAtPixel(evt.pixel, (feature) => {
                hoverFeature.value = feature
                return true // 只获取最顶层的要素
            }, {
                layerFilter: (layer) => layer === vectorLayer, // 只检测目标图层
            })

            if(hoverFeature.value){
                // 显示提示框（包含原始properties）
                tooltipData.value    = hoverFeature.value.getProperties()
                tooltipX.value       = evt.pixel[0] + 10
                tooltipY.value       = evt.pixel[1] + 10
                tooltipVisible.value = true
            }
            else{
                // 隐藏提示框
                tooltipVisible.value = false
                hoverFeature.value   = null
            }
        })

        // 自适应地图范围
        const extent = vectorSource.getExtent()
        map.getView().fit(extent, {
            padding : [ 50, 50, 50, 50 ],
            duration: 1000,
        })
    })
}

// 监听弹窗显示状态
watch(isOpen, (val) => {
    if(val){
        initMap()
    }
    else{
        // 关闭时销毁地图
        if(map){
            map.setTarget(null)
            map = null
        }
        tooltipVisible.value = false
        hoverFeature.value   = null
    }
})

// 组件卸载时清理地图
onUnmounted(() => {
    if(map){
        map.setTarget(null)
        map = null
    }
})

// 格式化权重类型显示名称
function formatWeightType(type){
    const types = {
        "KNN"               : "K最近邻",
        "DISTANCE_THRESHOLD": "距离阈值",
        "QUEEN"             : "皇后邻接",
        "ROOK"              : "rook邻接",
    }
    return types[type] || type
}
</script>

<style lang="scss" scoped>
.result_show {
    display: flex;
    gap: 10px;

    .left {
        flex: 1;

        .mapContainer {
            width: 100%;
            height: 400px;
            margin-bottom: 20px;
            position: relative;

            .custom-tooltip {
                position: absolute;
                background: rgba(0, 0, 0, 0.7);
                color: white;
                padding: 5px 10px;
                border-radius: 4px;
                font-size: 12px;
                z-index: 1000;
                pointer-events: none;
                max-width: 200px;

                p {
                    text-align: left;
                    margin: 3px 0;
                    line-height: 1.4;
                }
            }
        }

        .color-box {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 3px;
            margin: 0 5px;

            &.hh {
                background-color: #e74c3c;
            }

            &.ll {
                background-color: #3498db;
            }

            &.lh {
                background-color: #f39c12;
            }

            &.hl {
                background-color: #9b59b6;
            }

            &.ns {
                background-color: #95a5a6;
            }
        }
    }

    .right {
        flex: 1;

        .cluster-tag {
            display: inline-block;
            padding: 2px 8px;
            border-radius: 4px;
            color: white;
            font-size: 12px;

            &.hh {
                background-color: #e74c3c;
            }

            &.ll {
                background-color: #3498db;
            }

            &.lh {
                background-color: #f39c12;
            }

            &.hl {
                background-color: #9b59b6;
            }

            &.ns {
                background-color: #95a5a6;
            }
        }
    }
}
</style>

